#include "border_option_napi.h"
#include "hilog/log.h"

namespace ImageKnifeC {
void BorderOptionNapi::SetBorderOption(napi_env env, napi_value &value)
{
    napi_status status = napi_has_named_property(env, value, "width", &hasWidth);
    if (status == napi_ok && hasWidth) {
        napi_value width;
        napi_get_named_property(env, value, "width", &width);
        ParseWidth(env, width);
    }

    status= napi_has_named_property(env, value, "color", &hasColor);
    if (status == napi_ok && hasColor) {
        napi_value color;
        napi_get_named_property(env, value, "color", &color);
        ParseColor(env, color);
    }

    status= napi_has_named_property(env, value, "radius", &hasRadius);
    if (status == napi_ok && hasRadius) {
        napi_value radius;
        napi_get_named_property(env, value, "radius", &radius);
        ParseRadius(env, radius);
    }

    status= napi_has_named_property(env, value, "style", &hasStyle);
    if (status == napi_ok && hasStyle) {
        napi_value style;
        napi_get_named_property(env, value, "style", &style);
        ParseStyle(env, style);
    }
}

void BorderOptionNapi::ParseWidth(napi_env env, napi_value &value)
{
    bool hasProperty = false;
    bool typeMatched = false;
    napi_status status;

    // LocalizedEdgeWidths
    std::vector<std::string> names = {"top", "end", "bottom", "start"};
    const int namesSize = 4;
    for (int i = 0; i < namesSize; i++) {
        napi_value lengthMetrics;
        status = napi_has_named_property(env, value, names[i].c_str(), &hasProperty);
        if (status == napi_ok && hasProperty) {
            napi_get_named_property(env, value, names[i].c_str(), &lengthMetrics);
            status = napi_has_named_property(env, lengthMetrics, "value", &hasProperty);
            if (status == napi_ok && hasProperty) {
                typeMatched = true;
            }
        }
    }

    if (typeMatched) {
        OH_LOG_Print(LOG_APP, LOG_WARN, LOG_DOMAIN,
                     "BorderOption",
                     "Border width only support number for now");
        hasWidth = false;
        return;
    }

    // EdgeWidths
    names = {"top", "right", "bottom", "left"};

    for (int i = 0; i < namesSize; i++) {
        napi_value length;
        status = napi_has_named_property(env, value, names[i].c_str(), &hasProperty);
        if (status == napi_ok && hasProperty) {
            typeMatched = true;
            napi_get_named_property(env, value, names[i].c_str(), &length);
            width[i] = ParseLength(env, length);
        }
    }

    // Length for four edge
    if (!typeMatched) {
        width[0] = ParseLength(env, value);
    }
}

void BorderOptionNapi::ParseRadius(napi_env env, napi_value &value)
{
    bool hasProperty = false;
    bool typeMatched = false;
    napi_status status;

    std::vector<std::string> names = {"topLeft", "topRight", "bottomLeft", "bottomRight"};
    const int namesSize = 4;
    for (int i = 0; i < namesSize; i++) {
        napi_value lengthValue;
        status = napi_has_named_property(env, value, names[i].c_str(), &hasProperty);
        if (status == napi_ok && hasProperty) {
            typeMatched = true;
            napi_get_named_property(env, value, names[i].c_str(), &lengthValue);
            // LocalizedBorderRadiuses
            status = napi_has_named_property(env, lengthValue, "value", &hasProperty);
            if (status == napi_ok && hasProperty) {
                OH_LOG_Print(LOG_APP, LOG_WARN, LOG_DOMAIN,
                             "BorderOption",
                             "Border radius only support number for now");
                hasRadius = false;
            } else { //  BorderRadiuses
                radius[i] = ParseLength(env, lengthValue);
            }
        }
    }

    if (!typeMatched) {
        radius[0] = ParseLength(env, value);
    }
}

void BorderOptionNapi::ParseColor(napi_env env, napi_value &value)
{
    bool hasProperty = false;
    bool typeMatched = false;
    napi_status status;

    // LocalizedEdgeColors |  EdgeColors
    napi_value resourceColor;
    std::vector<std::string> names = {"top", "end", "bottom", "start"};
    const int namesSize = 4;
    for (int i = 0; i < namesSize; i++) {
        status = napi_has_named_property(env, value, names[i].c_str(), &hasProperty);
        if (status == napi_ok && hasProperty) {
            typeMatched = true;
            napi_get_named_property(env, value, names[i].c_str(), &resourceColor);
            color[i] = ParseResourceColor(env, resourceColor);
        }
    }

    status = napi_has_named_property(env, value, "right", &hasProperty);
    if (status == napi_ok && hasProperty) {
        typeMatched = true;
        napi_get_named_property(env, value, "right", &resourceColor);
        color[1] = ParseResourceColor(env, resourceColor);
    }

    status = napi_has_named_property(env, value, "left", &hasProperty);
    const int colorLeftIndex = 3;
    if (status == napi_ok && hasProperty) {
        typeMatched = true;
        napi_get_named_property(env, value, "left", &resourceColor);
        color[colorLeftIndex] = ParseResourceColor(env, resourceColor);
    }

    // ResourceColor
    if (!typeMatched) {
        color[0] = ParseResourceColor(env, value);
    }
}

void BorderOptionNapi::ParseStyle(napi_env env, napi_value &value)
{
    bool hasProperty = false;
    bool typeMatched = false;
    napi_status status;

    // EdgeStyles
    napi_value styleValue;
    std::vector<std::string> names = {"top", "right", "bottom", "left"};
    const int namesSize = 4;
    for (int i = 0; i < namesSize; i++) {
        status = napi_has_named_property(env, value, names[i].c_str(), &hasProperty);
        if (status == napi_ok && hasProperty) {
            typeMatched = true;
            napi_get_named_property(env, value, names[i].c_str(), &styleValue);
            style[i] = parseBorderStyle(env, styleValue);
        }
    }

    if (!typeMatched) {
        style[0] = parseBorderStyle(env, value);
    }
}

float BorderOptionNapi::ParseLength(napi_env env, napi_value &value)
{
    // string | number | Resource
    napi_valuetype type;
    if (napi_typeof(env, value, &type) == napi_ok && type == napi_string) {
        size_t length;
        napi_get_value_string_utf8(env, value, nullptr, 0, &length);
        char buf[length + 1];
        napi_get_value_string_utf8(env, value, buf, length+1, nullptr);
        return std::atof(buf);
    } else if (napi_typeof(env, value, &type) == napi_ok && type == napi_number) {
        double num;
        napi_get_value_double(env, value, &num);
        return num;
    } else {
        OH_LOG_Print(LOG_APP, LOG_WARN, LOG_DOMAIN,
                     "BorderOption",
                     "Border only support Length:number for now");
        return 0;
    }
}

uint32_t BorderOptionNapi::ParseResourceColor(napi_env env, napi_value &value)
{
    OH_LOG_Print(LOG_APP, LOG_WARN, LOG_DOMAIN,
                 "BorderOption",
                 "Border only support width radius for now");
    return 0; // black
}

int32_t BorderOptionNapi::parseBorderStyle(napi_env env, napi_value &value)
{
    // C: ARKUI_BORDER_STYLE_SOLID = 0, ARKUI_BORDER_STYLE_DASHED, ARKUI_BORDER_STYLE_DOTTED
    // JS: Dotted, Dashed, Solid
    OH_LOG_Print(LOG_APP, LOG_WARN, LOG_DOMAIN,
                 "BorderOption",
                 "Border only support width radius for now");
    return 0;
}
}